"""
RGB通道编辑器对话框
"""

import tkinter as tk
from tkinter import ttk, messagebox
from PIL import Image, ImageTk
import numpy as np
import cv2
from typing import Optional, Callable, Dict

from ..utils import get_logger


class ChannelEditorDialog:
    """RGB通道编辑器对话框"""
    
    def __init__(
        self,
        parent: tk.Tk,
        image: np.ndarray,
        on_apply: Optional[Callable] = None
    ):
        """
        初始化通道编辑器
        
        Args:
            parent: 父窗口
            image: 原始图片 (RGB)
            on_apply: 应用回调函数 (channel_image: np.ndarray, channel_config: dict)
        """
        self.parent = parent
        self.image = image
        self.on_apply = on_apply
        self.logger = get_logger(__name__)
        
        # 创建窗口
        self.window = tk.Toplevel(parent)
        self.window.title("RGB通道编辑器")
        self.window.geometry("1000x700")
        self.window.transient(parent)
        self.window.grab_set()
        
        # 通道状态
        self.channel_r_var = tk.BooleanVar(value=True)
        self.channel_g_var = tk.BooleanVar(value=True)
        self.channel_b_var = tk.BooleanVar(value=True)
        
        # 通道权重（用于混合）
        self.weight_r_var = tk.DoubleVar(value=1.0)
        self.weight_g_var = tk.DoubleVar(value=1.0)
        self.weight_b_var = tk.DoubleVar(value=1.0)
        
        # 预览模式
        self.preview_mode_var = tk.StringVar(value="combined")
        
        # 分离通道
        self.channel_r = image[:, :, 0]
        self.channel_g = image[:, :, 1]
        self.channel_b = image[:, :, 2]
        
        # 创建UI
        self._create_ui()
        
        # 初始预览
        self._update_preview()
    
    def _create_ui(self):
        """创建用户界面"""
        # 顶部说明
        info_frame = ttk.Frame(self.window, padding=10)
        info_frame.pack(fill=tk.X)
        
        ttk.Label(
            info_frame,
            text="📊 RGB通道编辑器",
            font=("Arial", 14, "bold")
        ).pack(side=tk.LEFT)
        
        ttk.Label(
            info_frame,
            text="通道图用于SAM输入识别mask，最终裁剪使用原图",
            font=("Arial", 10),
            foreground="gray"
        ).pack(side=tk.LEFT, padx=20)
        
        # 主容器
        main_container = ttk.Frame(self.window)
        main_container.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 左侧：控制面板
        control_frame = ttk.LabelFrame(main_container, text="通道控制", padding=10)
        control_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 5))
        
        # 红色通道
        r_frame = self._create_channel_control(
            control_frame, "红色通道 (R)", 
            self.channel_r_var, self.weight_r_var, "#ff4444"
        )
        r_frame.pack(fill=tk.X, pady=5)
        
        # 绿色通道
        g_frame = self._create_channel_control(
            control_frame, "绿色通道 (G)",
            self.channel_g_var, self.weight_g_var, "#44ff44"
        )
        g_frame.pack(fill=tk.X, pady=5)
        
        # 蓝色通道
        b_frame = self._create_channel_control(
            control_frame, "蓝色通道 (B)",
            self.channel_b_var, self.weight_b_var, "#4444ff"
        )
        b_frame.pack(fill=tk.X, pady=5)
        
        # 分隔线
        ttk.Separator(control_frame, orient=tk.HORIZONTAL).pack(fill=tk.X, pady=15)
        
        # 预览模式选择
        ttk.Label(control_frame, text="预览模式:", font=("Arial", 10, "bold")).pack(anchor=tk.W, pady=(5, 2))
        
        preview_modes = [
            ("组合视图", "combined"),
            ("仅红色通道", "r_only"),
            ("仅绿色通道", "g_only"),
            ("仅蓝色通道", "b_only"),
            ("灰度视图", "grayscale")
        ]
        
        for text, value in preview_modes:
            ttk.Radiobutton(
                control_frame,
                text=text,
                variable=self.preview_mode_var,
                value=value,
                command=self._update_preview
            ).pack(anchor=tk.W, pady=2)
        
        # 快捷按钮
        ttk.Separator(control_frame, orient=tk.HORIZONTAL).pack(fill=tk.X, pady=15)
        ttk.Label(control_frame, text="快捷操作:", font=("Arial", 10, "bold")).pack(anchor=tk.W, pady=(5, 5))
        
        quick_btn_frame = ttk.Frame(control_frame)
        quick_btn_frame.pack(fill=tk.X, pady=5)
        
        ttk.Button(
            quick_btn_frame,
            text="全选",
            command=self._select_all_channels,
            width=10
        ).pack(side=tk.LEFT, padx=2)
        
        ttk.Button(
            quick_btn_frame,
            text="全不选",
            command=self._deselect_all_channels,
            width=10
        ).pack(side=tk.LEFT, padx=2)
        
        ttk.Button(
            quick_btn_frame,
            text="反选",
            command=self._invert_channels,
            width=10
        ).pack(side=tk.LEFT, padx=2)
        
        # 重置按钮
        ttk.Button(
            control_frame,
            text="重置为默认",
            command=self._reset_to_default,
            width=30
        ).pack(pady=10)
        
        # 右侧：预览区域
        preview_frame = ttk.LabelFrame(main_container, text="预览", padding=10)
        preview_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        # 预览画布
        self.preview_canvas = tk.Canvas(
            preview_frame,
            bg="#2b2b2b",
            highlightthickness=1,
            highlightbackground="gray"
        )
        self.preview_canvas.pack(fill=tk.BOTH, expand=True)
        
        # 预览信息
        self.preview_info_label = ttk.Label(
            preview_frame,
            text="",
            font=("Arial", 9),
            foreground="gray"
        )
        self.preview_info_label.pack(pady=5)
        
        # 底部按钮
        button_frame = ttk.Frame(self.window, padding=10)
        button_frame.pack(fill=tk.X)
        
        # 提示信息
        ttk.Label(
            button_frame,
            text="💡 将通道图作为SAM输入，分割后用mask裁剪原图（支持撤销）",
            foreground="#0066cc",
            font=("Arial", 9, "italic")
        ).pack(side=tk.LEFT, padx=10)
        
        # 按钮
        ttk.Button(
            button_frame,
            text="取消",
            command=self.window.destroy,
            width=12
        ).pack(side=tk.RIGHT, padx=5)
        
        ttk.Button(
            button_frame,
            text="应用通道图",
            command=self._on_apply,
            bootstyle="success",
            width=15
        ).pack(side=tk.RIGHT, padx=5)
    
    def _create_channel_control(
        self,
        parent: ttk.Frame,
        label: str,
        enabled_var: tk.BooleanVar,
        weight_var: tk.DoubleVar,
        color: str
    ) -> ttk.Frame:
        """创建单个通道控制"""
        frame = ttk.LabelFrame(parent, text=label, padding=5)
        
        # 启用复选框
        check = ttk.Checkbutton(
            frame,
            text="启用",
            variable=enabled_var,
            command=self._update_preview
        )
        check.pack(anchor=tk.W, pady=2)
        
        # 权重滑块
        weight_frame = ttk.Frame(frame)
        weight_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(weight_frame, text="权重:", width=6).pack(side=tk.LEFT)
        
        scale = ttk.Scale(
            weight_frame,
            from_=0.0,
            to=2.0,
            orient=tk.HORIZONTAL,
            variable=weight_var,
            command=lambda v: self._on_weight_change()
        )
        scale.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        
        value_label = ttk.Label(weight_frame, text="1.00", width=5)
        value_label.pack(side=tk.LEFT)
        
        # 保存标签引用以便更新
        frame.value_label = value_label
        frame.weight_var = weight_var
        
        return frame
    
    def _on_weight_change(self):
        """权重变化回调"""
        # 更新所有权重标签
        for widget in [w for w in self.window.winfo_children() if isinstance(w, ttk.Frame)]:
            for child in widget.winfo_children():
                if hasattr(child, 'value_label') and hasattr(child, 'weight_var'):
                    child.value_label.config(text=f"{child.weight_var.get():.2f}")
        
        # 更新预览
        self._update_preview()
    
    def _update_preview(self):
        """更新预览"""
        try:
            # 获取当前配置
            use_r = self.channel_r_var.get()
            use_g = self.channel_g_var.get()
            use_b = self.channel_b_var.get()
            
            weight_r = self.weight_r_var.get()
            weight_g = self.weight_g_var.get()
            weight_b = self.weight_b_var.get()
            
            mode = self.preview_mode_var.get()
            
            # 生成预览图像
            if mode == "combined":
                # 组合视图
                preview = self._generate_combined_image(use_r, use_g, use_b, weight_r, weight_g, weight_b)
            elif mode == "r_only":
                preview = np.stack([self.channel_r] * 3, axis=-1) if use_r else np.zeros_like(self.image)
            elif mode == "g_only":
                preview = np.stack([self.channel_g] * 3, axis=-1) if use_g else np.zeros_like(self.image)
            elif mode == "b_only":
                preview = np.stack([self.channel_b] * 3, axis=-1) if use_b else np.zeros_like(self.image)
            elif mode == "grayscale":
                preview = self._generate_combined_image(use_r, use_g, use_b, weight_r, weight_g, weight_b)
                preview = cv2.cvtColor(preview, cv2.COLOR_RGB2GRAY)
                preview = np.stack([preview] * 3, axis=-1)
            
            # 显示预览
            self._display_preview(preview)
            
            # 更新信息
            enabled_channels = []
            if use_r:
                enabled_channels.append(f"R({weight_r:.1f})")
            if use_g:
                enabled_channels.append(f"G({weight_g:.1f})")
            if use_b:
                enabled_channels.append(f"B({weight_b:.1f})")
            
            if enabled_channels:
                info = f"启用通道: {', '.join(enabled_channels)}"
            else:
                info = "⚠️ 警告：未启用任何通道"
            
            self.preview_info_label.config(text=info)
            
        except Exception as e:
            self.logger.error(f"更新预览失败: {e}", exc_info=True)
    
    def _generate_combined_image(
        self,
        use_r: bool,
        use_g: bool,
        use_b: bool,
        weight_r: float,
        weight_g: float,
        weight_b: float
    ) -> np.ndarray:
        """生成组合通道图像"""
        h, w = self.image.shape[:2]
        result = np.zeros((h, w, 3), dtype=np.uint8)
        
        if use_r:
            result[:, :, 0] = np.clip(self.channel_r * weight_r, 0, 255).astype(np.uint8)
        
        if use_g:
            result[:, :, 1] = np.clip(self.channel_g * weight_g, 0, 255).astype(np.uint8)
        
        if use_b:
            result[:, :, 2] = np.clip(self.channel_b * weight_b, 0, 255).astype(np.uint8)
        
        return result
    
    def _display_preview(self, preview_image: np.ndarray):
        """显示预览图像"""
        # 清空画布
        self.preview_canvas.delete("all")
        
        # 获取画布尺寸
        self.preview_canvas.update()
        canvas_width = self.preview_canvas.winfo_width()
        canvas_height = self.preview_canvas.winfo_height()
        
        if canvas_width <= 1 or canvas_height <= 1:
            canvas_width = 600
            canvas_height = 500
        
        # 调整图片大小
        h, w = preview_image.shape[:2]
        scale = min(canvas_width / w, canvas_height / h) * 0.95
        new_w = int(w * scale)
        new_h = int(h * scale)
        
        resized = cv2.resize(preview_image, (new_w, new_h))
        
        # 转换为PIL图像
        pil_image = Image.fromarray(resized)
        photo = ImageTk.PhotoImage(pil_image)
        
        # 居中显示
        x = (canvas_width - new_w) // 2
        y = (canvas_height - new_h) // 2
        
        self.preview_canvas.create_image(x, y, anchor=tk.NW, image=photo)
        self.preview_canvas.image = photo
    
    def _select_all_channels(self):
        """全选所有通道"""
        self.channel_r_var.set(True)
        self.channel_g_var.set(True)
        self.channel_b_var.set(True)
        self._update_preview()
    
    def _deselect_all_channels(self):
        """取消所有通道"""
        self.channel_r_var.set(False)
        self.channel_g_var.set(False)
        self.channel_b_var.set(False)
        self._update_preview()
    
    def _invert_channels(self):
        """反选通道"""
        self.channel_r_var.set(not self.channel_r_var.get())
        self.channel_g_var.set(not self.channel_g_var.get())
        self.channel_b_var.set(not self.channel_b_var.get())
        self._update_preview()
    
    def _reset_to_default(self):
        """重置为默认"""
        self.channel_r_var.set(True)
        self.channel_g_var.set(True)
        self.channel_b_var.set(True)
        self.weight_r_var.set(1.0)
        self.weight_g_var.set(1.0)
        self.weight_b_var.set(1.0)
        self.preview_mode_var.set("combined")
        self._on_weight_change()
        self._update_preview()
    
    def _on_apply(self):
        """应用按钮回调"""
        # 检查至少启用一个通道
        if not (self.channel_r_var.get() or self.channel_g_var.get() or self.channel_b_var.get()):
            messagebox.showwarning("警告", "请至少启用一个通道！", parent=self.window)
            return
        
        # 生成处理后的图像
        channel_image = self._generate_combined_image(
            self.channel_r_var.get(),
            self.channel_g_var.get(),
            self.channel_b_var.get(),
            self.weight_r_var.get(),
            self.weight_g_var.get(),
            self.weight_b_var.get()
        )
        
        # 配置信息
        channel_config = {
            'enabled_channels': {
                'r': self.channel_r_var.get(),
                'g': self.channel_g_var.get(),
                'b': self.channel_b_var.get()
            },
            'weights': {
                'r': self.weight_r_var.get(),
                'g': self.weight_g_var.get(),
                'b': self.weight_b_var.get()
            }
        }
        
        self.logger.info(f"应用通道配置: {channel_config}")
        
        # 调用回调
        if self.on_apply:
            self.on_apply(channel_image, channel_config)
        
        # 关闭窗口
        self.window.destroy()

